package com.csw.android.dev_utils.ex

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelStoreOwner
import com.csw.android.dev_utils.ex.ActivityEx.bindVM

object FragmentEx {

    /**
     * 绑定Fragment上的ViewModel
     */
    inline fun <reified V : ViewModel> Fragment.bindVM(): V {
        return this.get(V::class.java)
    }

    /**
     * 查找ViewModel，若当前Fragment没有实例，则继续往上查找，直到Activity
     *
     * @param V ViewModel类型
     * @return 已存在的ViewModel实例，若不存在实例，返回空
     */
    inline fun <reified V : ViewModel> Fragment.findVM() = findVM(V::class.java)

    /**
     * 查找ViewModel，若当前Fragment没有实例，则继续往上查找，直到Activity
     *
     * @param V ViewModel类型
     * @param clazz ViewModel的class
     * @return 已存在的ViewModel实例，若不存在实例，返回空
     */
    fun <V : ViewModel> Fragment.findVM(clazz: Class<V>): V? {
        var vmStoreOwner: ViewModelStoreOwner? = this
        var fragment: Fragment? = this
        while (vmStoreOwner != null) {
            vmStoreOwner.query(clazz)?.run {
                //找到了直接返回
                return this
            }
            vmStoreOwner = null
            //查询父fragment
            fragment?.parentFragment?.apply {
                vmStoreOwner = this
                fragment = this
            }
            //没有父fragment，查询activity
            if (vmStoreOwner == null) {
                vmStoreOwner = fragment?.activity
                fragment = null
            }
        }
        return null
    }

    /**
     * 绑定Activity上的ViewModel
     */
    inline fun <reified V : ViewModel> Fragment.bindActivityVM(): V {
        return requireActivity().bindVM()
    }

    /**
     * 确保参数对象不为空
     */
    fun Fragment.ensureArguments(): Bundle {
        return arguments ?: Bundle()
    }

    /**
     * 获取AppCompatActivity，若所依附的activity不是AppCompatActivity，则返回空
     */
    fun Fragment.getAppCompatActivity(): AppCompatActivity? {
        val a = activity
        if (a is AppCompatActivity) {
            return a
        }
        return null
    }
}